import { addData, getData, updateData } from '@vimi/utils-api'
import { getStaff } from '@/common/api/auth'
import { dateValidate, dateFromString } from '@vimi/utils-tool'
import { dateFormat } from '@/common/utils/common'
import { SERVICE_NAME } from '@/credit/plugins/constant'

// @ts-check

const relatedTableName = 'customer_related'
const contractTableName = 'entrust_contract'
const approvalTableName = 'contract_approval'
/**
 * 贷款品种
 */
export const enumLoanVarieties = {
  1: '流贷',
  2: '固贷',
  3: '其他',
}

export const enumProcessLabel = {
  0: '权限内',
  1: '权限外',
}

// ================================= api ==================================

/**
 * 获取项目信息（关联表）
 * @param {string} relatedId 关联ID
 */
export const getRelated = relatedId =>
  getData(SERVICE_NAME, relatedTableName, {
    'customer_related_id.eq': relatedId,
  }).then(res => res?.data?.[0] ?? {})

/**
 * 更新项目合同审批信息
 * @param {*} id 关联ID
 * @param {*} data 更新数据
 */
export const updateRelatedContractStatus = (id, status) =>
  updateData(SERVICE_NAME, relatedTableName, id, {
    contract_approval_status: status,
  })

export const updateRelatedData = (id, data) => updateData(SERVICE_NAME, relatedTableName, id, data)

/**
 * 获取合同审批表
 * @param {string} relatedId 关联ID
 */
export const getApproval = relatedId =>
  getData(SERVICE_NAME, approvalTableName, {
    customer_related_id: relatedId,
  }).then(res => res?.data?.[0] ?? {})

/**
 * 更新合同审批列表
 * @param {*} id 合同审批表ID
 * @param {*} data 更新数据
 */
export const updateApproval = (id, data) => updateData(SERVICE_NAME, approvalTableName, id, data)

/**
 * 添加合同审批列表
 * @param {*} data 添加数据
 */
export const addApproval = data => addData(SERVICE_NAME, approvalTableName, data)

/**
 * 更新委托担保合同
 * @param {string} id 合同ID
 * @param {Record<string, any>} data 更新数据
 */
export const updateContract = (id, data) => updateData(SERVICE_NAME, contractTableName, id, data)

// 获取有权审批人
export const getAuthPerson = () =>
  getStaff().then(res => {
    const data = res.data || []
    let auth = {}
    let corp = {}
    let riskManager = {}
    const committee = [] // 审批委员会
    for (const p of data) {
      if (+p.isAuthorizedPerson === 1) {
        auth = p
      }
      if (p.job === 'org_corp') {
        corp = p
      } else if (p.job === 'org_r_manage') {
        riskManager = p
      }
      if (+p.isApprovalRep === 1) {
        committee.push(p)
      }
    }
    return {
      corp: auth.userId ? auth : corp,
      riskManager,
      committee,
    }
  })

/**
 * 更新合同审批内容
 * @param {*} approvalId 合同审批ID
 * @param {*} bps busProcess
 * @param {*} param2 need data
 */
export const approvalComment = (
  approvalId,
  bps,
  { name, status, approval, solidApproval, queryId }
) => {
  const date = dateFormat(new Date())
  const afters = []
  let data = {}
  for (const bp of bps) {
    const { keys, beforeSave, afterSave } = bp
    const comment = approval[keys.comment]
    const solidComment = solidApproval[keys.comment]

    // 一人多种权限时，如没有更改意见内容则不用修改对应角色的信息
    if (solidComment && comment === solidComment) {
      continue
    }

    data[keys.name] = name
    data[keys.comment] = comment
    data[keys.date] = date
    data[keys.status] = status
    data.customer_related_id = queryId
    if (beforeSave) {
      data = beforeSave(data)
    }

    if (afterSave && typeof afterSave === 'function') {
      afters.push(afterSave)
    }
  }

  return updateApproval(approvalId, data).then(res => {
    if (afters.length) {
      return Promise.all(afters.map(it => it()))
    }
    return res
  })
}

// ============================ utils ================================

/**
 * 根据放款时间计算担保期限，以月为单位
 * @param {string} start 开始时间
 * @param {string} end 结束时间
 * @returns {number}
 */
export const calcMonth = (start, end) => {
  const startDate = dateFromString(start)
  let endDate = dateFromString(end)

  if (!dateValidate(startDate) || !dateValidate(endDate)) {
    return null
  }

  endDate = new Date(endDate + 8.64e7)
  const monthDelta = endDate.getMonth() - startDate.getMonth() < 0 ? 1 : 0
  return (endDate.getFullYear() - startDate.getFullYear()) * 12 - monthDelta
}

/**
 * 根据用户规则计算是否可以编辑
 * @param {any} param0 包括用户等信息
 * @param {{user:any, org:any}} param1 判断规则
 */
export const calcRole = ({ user = {}, org = {} }, { user: currentUser, org: currentOrg }) => {
  const match = (dVal, mVal) => {
    if (Array.isArray(dVal)) {
      return dVal.includes(mVal)
    } else if (dVal === mVal) {
      return true
    }
    return false
  }

  const userKeys = Object.keys(user)
  for (const uk of userKeys) {
    if (!match(user[uk], currentUser[uk])) {
      return false
    }
  }

  const orgKeys = Object.keys(org)
  for (const ok of orgKeys) {
    if (!match(org[ok], currentOrg[ok])) {
      return false
    }
  }

  return true
}

/**
 * 根据判断规则计算当前状态是否可以编辑
 * @param {number[]} currentStatus 需要判断的状态数组
 * @param {string} fmt 判断规则
 */
export const calcStatus = (currentStatus, fmt) => {
  const fmtArr = fmt.split(',')
  /** @param {number} i index */
  const match = i => {
    // 支持格式：=1, <1, <=1, >1, >=1, !1, *, in1|2|3
    const str = (fmtArr[i] || '').replace(/\s/g, '')
    if (str === '*') return true

    const [, op, val] = str.match(/(=|<|<=|>|>=|!|in)(\d.*)/) || []
    if (!op || !val) return false

    const s = currentStatus[i]
    switch (op) {
      case '=':
        return s === +val
      case '<':
        return s < +val
      case '<=':
        return s <= +val
      case '>':
        return s > +val
      case '>=':
        return s >= +val
      case '!':
        return s !== +val
      case 'in':
        return val
          .split('|')
          .map(it => +it)
          .includes(s)
      default:
        return false
    }
  }

  for (let i = 0; i < fmtArr.length; i++) {
    if (!match(i)) {
      return false
    }
  }
  return true
}

/**
 * 验证
 * @param {*} data formData
 * @param {*} bps busProcesses
 */
export const validateProcess = (data, bps) => {
  const toValid = v => {
    if (v.required) {
      v.validator = h => !!h
    }
    return v
  }
  const flatValid = validator => {
    const res = []
    if (Array.isArray(validator)) {
      res.push(...validator.map(it => toValid(it)))
    } else {
      res.push(toValid(validator))
    }
    return res
  }

  for (const bp of bps) {
    const { validators, keys } = bp
    if (!validators) {
      continue
    }

    const validKeys = Object.keys(validators)
    for (const vk of validKeys) {
      const val = data[keys[vk]]
      const allValidator = flatValid(validators[vk])
      for (const eachValid of allValidator) {
        if (!eachValid.validator(val)) {
          return eachValid.message
        }
      }
    }
  }

  return false
}

/**
 * 获取权限内流程状态
 * @param {{
 *  approval: object; // 合同审批表数据
 *  related: object; // 关联表数据
 *  authPerson: object; // 有权审批人
 * }} param 判断流程状态需要用到的数据
 */
export const getInProcess = ({ approval, related, authPerson, user, org }) => {
  const status = [
    +approval.res_a_status,
    +approval.res_bus_status,
    +approval.res_risk_point_status,
    +approval.res_risk_status,
    +approval.res_corp_status,
  ]
  return [
    {
      type: 1,
      status: '=1,*,=0,=0,=0',
      role: {
        user: {
          orgRegionLever: [2, 3],
          job: 'org_c_manage',
        },
      },
      editable: false,
      signLabel: '业务部负责人',
      signLevel: 2,
      signName: [{ label: '签字', key: 'res_bus_person' }],
      keys: {
        name: 'res_bus_person',
        status: 'res_bus_status',
        date: 'res_bus_date',
        comment: 'res_bus_option',
      },
      validators: {
        comment: [{ required: true, message: '请输入业务部负责人意见' }],
      },
    },
    {
      type: 2,
      status: '=1,=1,*,=0,=0',
      role: {
        user: {
          orgRegionLever: [2, 3],
          userId: related.res_user_id_risk_point,
        },
      },
      editable: false,
      signLabel: '风控审查人',
      signLevel: 2,
      signName: [{ label: '签字', key: 'res_risk_point_person' }],
      keys: {
        name: 'res_risk_point_person',
        status: 'res_risk_point_status',
        date: 'res_risk_point_date',
        comment: 'res_risk_point_option',
      },
      validators: {
        comment: [{ required: true, message: '请输入风控审查人员意见' }],
      },
    },
    {
      type: 3,
      status: '=1,=1,=1,*,=0',
      role: {
        user: {
          orgRegionLever: [2, 3],
          job: 'org_r_manage',
        },
      },
      editable: false,
      signLabel: '风控部负责人',
      signLevel: 2,
      signName: [{ label: '签字', key: 'res_risk_person' }],
      keys: {
        name: 'res_risk_person',
        status: 'res_risk_status',
        date: 'res_risk_date',
        comment: 'res_risk_option',
      },
      validators: {
        comment: [{ required: true, message: '请输入风控部负责人意见' }],
      },
    },
    {
      type: 5,
      status: '=1,=1,=1,=1,=0',
      role: {
        user: {
          orgRegionLever: [2, 3],
          userId: authPerson.userId,
        },
      },
      editable: false,
      signLabel: '有权审批人',
      signLevel: 2,
      signName: [{ label: '签字', key: 'res_corp_person' }],
      keys: {
        name: 'res_corp_person',
        status: 'res_corp_status',
        date: 'res_corp_date',
        comment: 'res_corp_option',
      },
      validators: {
        comment: [{ required: true, message: '请输入有权审批人意见' }],
      },
      // afterSave: () => Promise.all([
      //   updateRelatedData(related.customer_related_id, {
      //     contract_approval_status: 2
      //   })
      // ])
    },
  ].map(it => ({
    ...it,
    editable: calcRole(it.role, { user, org }) && calcStatus(status, it.status),
  }))
}

/**
 * 获取权限外流程状态
 * @param {{
 *  approval: object; // 合同审批表数据
 *  related: object; // 关联表数据
 *  authPerson: object; // 有权审批人
 *  riskManager: object; // 风控负责人（姓名）
 * }} param 判断流程状态需要用到的数据
 */
export const getOutProcess = ({ approval, _, authPerson, __, user, org }) => {
  const status = [+approval.res_a_status, +approval.res_bus_status, +approval.res_corp_status]

  return [
    {
      type: 1,
      status: '=1,*,=0',
      role: {
        user: {
          orgRegionLever: [2, 3],
          job: 'org_c_manage',
        },
      },
      editable: false,
      signLabel: '业务部负责人',
      signLevel: 2,
      signName: [{ label: '签字', key: 'res_bus_person' }],
      keys: {
        name: 'res_bus_person',
        status: 'res_bus_status',
        date: 'res_bus_date',
        comment: 'res_bus_option',
      },
      validators: {
        comment: [{ required: true, message: '请输入业务部负责人意见' }],
      },
    },
    {
      type: 2,
      status: '=1,=1,=0',
      role: {
        user: {
          orgRegionLever: [2, 3],
          userId: authPerson.userId,
        },
      },
      editable: false,
      signLabel: '有权审批人',
      signLevel: 2,
      signName: [{ label: '签字', key: 'res_corp_person' }],
      keys: {
        name: 'res_corp_person',
        status: 'res_corp_status',
        date: 'res_corp_date',
        comment: 'res_corp_option',
      },
      validators: {
        comment: [{ required: true, message: '请输入有权审批人意见' }],
      },
    },
  ].map(it => ({
    ...it,
    editable: calcRole(it.role, { user, org }) && calcStatus(status, it.status),
  }))
}

/**
 * 计算合同审批可编辑状态
 * @param {{
 *  approval: object; // 合同审批表数据
 *  related: object; // 关联表数据
 *  authPerson: object; // 有权审批人
 *  riskManager: object; // 风控负责人（姓名）
 * }} needData 判断流程状态需要用到的数据
 */
export const getProcessEditable = needData => {
  const enumProcessHandler = {
    0: getInProcess,
    1: getOutProcess,
  }
  const busProcess =
    enumProcessHandler[needData.related.process_status] || (() => [{ editable: false }])
  return busProcess(needData).some(it => it.editable)
}
